package app.component;

import com.dj.gateway.app.authorization.dto.DJUserInfo;
import com.dj.gateway.app.authorization.dto.MemberInfo;
import com.dj.gateway.app.utils.JsonUtils;
import com.google.common.collect.Lists;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DJJsonSerializationStrategy implements RedisTokenStoreSerializationStrategy {

    @Override
    public <T> T deserialize(byte[] bytes, Class<T> clazz) {
        if (bytes == null){
            return null;
        }
        String str = new String(bytes, Charset.forName("UTF-8"));
        if (clazz == OAuth2Authentication.class){
            Map map = JsonUtils.toObject(str, Map.class);
            String clientId = "mportal";
            String clientSecret = "mportal";
            ClientDetails clientDetails = new BaseClientDetails();
            ((BaseClientDetails) clientDetails).setClientId(clientId);
            List scops = Lists.newArrayList();
            scops.add("all");
            ((BaseClientDetails) clientDetails).setScope(scops);

            // grantType 为自定义的"custom"
            TokenRequest tokenRequest = new TokenRequest(new HashMap<>(), clientId, clientDetails.getScope(), "custom");
            OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);


            Map userAuthenticationObj = (Map) map.get("userAuthentication");
            DJUserInfo djUserInfo = new DJUserInfo();
            CardPasswordAuthenticationToken cardPasswordAuthenticationToken = null;
            if (userAuthenticationObj != null) {
                Map principal = (Map) userAuthenticationObj.get("principal");
                if (principal != null) {
                    List<Map> authorities = (List<Map>) principal.get("authorities");
                    List<SimpleGrantedAuthority> authoritiesList = new ArrayList<>();
                    if (authorities != null) {
                        for (Map item : authorities) {
                            SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority((String) item.get("authority"));
                            authoritiesList.add(simpleGrantedAuthority);
                        }
                    }
                    djUserInfo.setAuthorities(authoritiesList);
                    Object memberInfoObj = principal.get("userData");
                    String memberInfoObjStr = JsonUtils.toJson(memberInfoObj);
                    MemberInfo info = JsonUtils.toObject(memberInfoObjStr, MemberInfo.class);
                    djUserInfo.setUserData(info);
                }
            }

            cardPasswordAuthenticationToken = new CardPasswordAuthenticationToken(djUserInfo, djUserInfo.getAuthorities());
            OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, cardPasswordAuthenticationToken);
            return (T) oAuth2Authentication;


        }else{
            return JsonUtils.toObject(str, clazz);
        }

    }

    @Override
    public String deserializeString(byte[] bytes) {
        if (bytes == null){
            return null;
        }
        return new String(bytes,Charset.forName("UTF-8"));
    }

    @Override
    public byte[] serialize(Object object) {
        String s = JsonUtils.toJson(object);
        return serialize(s);
    }

    @Override
    public byte[] serialize(String data) {
        return data.getBytes(Charset.forName("UTF-8"));
    }
}
